<?php
/*
** Zabbix
** Copyright (C) 2001-2021 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

require_once dirname(__FILE__).'/../include/CLegacyWebTest.php';
require_once dirname(__FILE__).'/../../include/items.inc.php';
require_once dirname(__FILE__).'/../../include/classes/api/services/CItemGeneral.php';
require_once dirname(__FILE__).'/../../include/classes/api/services/CItem.php';

use Facebook\WebDriver\WebDriverBy;

/**
 * @backup items
 * TODO: The following annotation (ignoreBrowserErrors) is added to ignore JS errors generated by information type
 *       dropdown field when "on change" event is fired before "on focus" event is fired.
 * @ignoreBrowserErrors
 */
class testFormItem extends CLegacyWebTest {

	/**
	 * The name of the test host created in the test data set.
	 *
	 * @var string
	 */
	protected $host = 'Simple form test host';

	/**
	 * The name of the item created in the test data set.
	 *
	 * @var string
	 */
	protected $item = 'testFormItem1';

	// Returns layout data
	public static function layout() {
		return [
			[
				['type' => 'Zabbix agent', 'host' => 'Simple form test host']
			],
			[
				['host' => 'Simple form test host', 'key' => 'test-item-form1']
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Numeric (float)', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Character', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Log', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Text', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent (active)', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Simple check', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Numeric (float)', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Character', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Log', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Text', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP trap', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix internal', 'host' => 'Simple form test host'	]
			],
			[
				[
					'type' => 'Zabbix internal',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				['type' => 'Zabbix trapper', 'host' => 'Simple form test host']
			],
			[
				['type' => 'External check', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Database monitor', 'host' => 'Simple form test host']
			],
			[
				['type' => 'IPMI agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SSH agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Public key', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Password', 'host' => 'Simple form test host']
			],
			[
				[
					'type' => 'SSH agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				[
					'type' => 'SSH agent',
					'authtype' => 'Password',
					'value_type' => 'Character',
					'host' => 'Simple form test host'
				]
			],
			[
				['type' => 'TELNET agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'JMX agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Calculated', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'template' => 'Inheritance test template']
			],
			[
				[
					'type' => 'Zabbix agent',
					'template' => 'Inheritance test template',
					'key' => 'test-inheritance-item1'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'template' => 'Template inheritance test host',
					'key' => 'test-inheritance-item1'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (float)',
					'template' => 'Inheritance test template'
					]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Character',
					'template' => 'Inheritance test template'
				]
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Log', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Text', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Zabbix agent (active)', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Simple check', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Numeric (float)', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Character', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Text', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP trap', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Zabbix internal', 'template' => 'Inheritance test template']
			],
			[
				[
					'type' => 'Zabbix internal',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix internal',
					'template' => 'Inheritance test template',
					'key' => 'test-inheritance-item1'
				]
			],
			[
				['type' => 'Zabbix trapper', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'External check', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Database monitor', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'IPMI agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SSH agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Public key', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Password', 'template' => 'Inheritance test template']
			],
			[
				[
					'type' => 'SSH agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'SSH agent',
					'authtype' => 'Password',
					'value_type' => 'Character',
					'template' => 'Inheritance test template'
				]
			],
			[
				['type' => 'TELNET agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'JMX agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Calculated', 'template' => 'Inheritance test template']
			],
			[
				[
					'host' => 'Template inheritance test host',
					'hostTemplate' => 'Inheritance test template',
					'key' => 'test-inheritance-item-preprocessing',
					'preprocessing' => true
				]
			]
		];
	}

	/**
	 * @dataProvider layout
	 */
	public function testFormItem_CheckLayout($data) {
		$context = array_key_exists('host', $data) ? 'host' : 'template';
		$host_name = array_key_exists('host', $data) ? $data['host'] : $data['template'];

		$dbResult = DBselect('SELECT hostid,status FROM hosts WHERE host='.zbx_dbstr($host_name));
		$host_info = DBfetch($dbResult);

		$this->assertNotEquals($host_info, null);

		$hostid = $host_info['hostid'];
		$status = $host_info['status'];

		if (isset($data['key'])) {
			$dbResult = DBselect(
				'SELECT itemid,templateid'.
				' FROM items'.
				' WHERE hostid='.$hostid.
					' AND key_='.zbx_dbstr($data['key'])
			);
			$template_info = DBfetch($dbResult);

			$this->assertNotEquals($template_info, null);

			$itemid = $template_info['itemid'];
			if (0 != $template_info['templateid'])
				$templateid = $template_info['templateid'];
		}

		$this->zbxTestLogin(
			'items.php?form='.(isset($itemid) ? 'update' : 'create').
			'&hostid='.$hostid.(isset($itemid) ? '&itemid='.$itemid : '').'&context='.$context
		);

		$this->zbxTestCheckTitle('Configuration of items');
		$this->zbxTestCheckHeader('Items');

		if (isset($templateid)) {
			$this->zbxTestTextPresent('Parent items');
			if (isset($data['hostTemplate'])) {
				$this->zbxTestAssertElementPresentXpath("//*[@id='itemFormList']/li[1]/div[2]/a[text()='".$data['hostTemplate']."']");
			}
		}
		else {
			$this->zbxTestTextNotPresent('Parent items');
		}

		$this->zbxTestTextPresent('Name');
		$this->zbxTestAssertVisibleId('name');
		$this->zbxTestAssertAttribute("//input[@id='name']", 'maxlength', 255);
		$this->zbxTestAssertAttribute("//input[@id='name']", 'size', 20);
		$this->zbxTestAssertAttribute("//input[@id='name']", 'autofocus');
		if (isset($templateid)) {
			$this->zbxTestAssertAttribute("//input[@id='name']", 'readonly');
		}

		$this->zbxTestTextPresent('Type');
		if (!isset($templateid)) {
			$this->zbxTestAssertVisibleId('type');
			$this->zbxTestDropdownHasOptions('type', [
				'Zabbix agent',
				'Zabbix agent (active)',
				'Simple check',
				'SNMP agent',
				'SNMP trap',
				'Zabbix internal',
				'Zabbix trapper',
				'External check',
				'Database monitor',
				'IPMI agent',
				'SSH agent',
				'TELNET agent',
				'JMX agent',
				'Calculated'
			]);
			if (isset($data['type'])) {
				$this->zbxTestDropdownSelect('type', $data['type']);
				$type = $data['type'];
			}
			else {
				$type = $this->zbxTestGetSelectedLabel('type');
			}
		}
		else {
			$this->zbxTestAssertVisibleId('type');
			$this->zbxTestAssertAttribute("//z-select[@id='type']", 'readonly');

			$type = $this->zbxTestGetSelectedLabel('type');
		}

		$this->zbxTestTextPresent('Key');
		$this->zbxTestAssertVisibleId('key');
		$this->zbxTestAssertAttribute("//input[@id='key']", 'maxlength', 2048);
		$this->zbxTestAssertAttribute("//input[@id='key']", 'size', 20);
		if (!isset($templateid)) {
			$this->zbxTestAssertElementPresentId('keyButton');
		}
		else {
			$this->zbxTestAssertAttribute("//input[@id='key']", 'readonly');
		}

		if ($type == 'Database monitor' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', 'db.odbc.select[<unique short description>,<dsn>,<connection string>]');
		}

		if ($type == 'SSH agent' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', 'ssh.run[<unique short description>,<ip>,<port>,<encoding>]');
		}

		if ($type == 'TELNET agent' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', 'telnet.run[<unique short description>,<ip>,<port>,<encoding>]');
		}

		if ($type == 'JMX agent' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', '');
			$this->zbxTestAssertElementNotPresentXpath("//button[@id='keyButton'][@disabled]");
		}

		if (isset($templateid)) {
			$value_type = $this->zbxTestGetSelectedLabel('value_type');
		}
		elseif (isset($data['value_type'])) {
			$this->zbxTestDropdownSelect('value_type', $data['value_type']);
			$value_type = $data['value_type'];
		}
		else {
			$value_type = $this->zbxTestGetSelectedLabel('value_type');
		}

		if ($type == 'SSH agent') {
			if (isset($data['authtype'])) {
				$this->zbxTestDropdownSelect('authtype', $data['authtype']);
				$authtype = $data['authtype'];
			}
			else {
				$authtype = $this->zbxTestGetSelectedLabel('authtype');
			}
		}

		if ($type == 'Database monitor') {
			$this->zbxTestTextPresent('SQL query');
			$this->zbxTestAssertVisibleId('params_ap');
			$this->zbxTestAssertAttribute("//textarea[@id='params_ap']", 'rows', 7);
			$this->zbxTestAssertElementValue('params_ap', '');
		}
		else {
			$this->zbxTestTextNotPresent('Additional parameters');
			$this->zbxTestAssertNotVisibleId('params_ap');
		}

		if ($type == 'SSH agent' || $type == 'TELNET agent' ) {
			$this->zbxTestTextPresent('Executed script');
			$this->zbxTestAssertVisibleId('params_es');
			$this->zbxTestAssertAttribute("//textarea[@id='params_es']", 'rows', 7);
		}
		else {
			$this->zbxTestTextNotVisible('Executed script');
			$this->zbxTestAssertNotVisibleId('params_es');
		}

		if ($type == 'Calculated') {
			$this->zbxTestTextPresent('Formula');
			$this->zbxTestAssertVisibleId('params_f');
			$this->zbxTestAssertAttribute("//textarea[@id='params_f']", 'rows', 7);
		}
		else {
			$this->zbxTestTextNotVisible('Formula');
			$this->zbxTestAssertNotVisibleId('params_f');
		}

		if ($status != HOST_STATUS_TEMPLATE) {
			$interfaceType = itemTypeInterface($this->zbxTestGetValue('//*[@id="type"]'));
			switch ($interfaceType) {
				case INTERFACE_TYPE_AGENT :
				case INTERFACE_TYPE_SNMP :
				case INTERFACE_TYPE_JMX :
				case INTERFACE_TYPE_IPMI :
				case INTERFACE_TYPE_ANY :
					$this->zbxTestTextPresent('Host interface');
					$dbInterfaces = DBfetchArray(DBselect(
						'SELECT type,ip,port'.
						' FROM interface'.
						' WHERE hostid='.$hostid.
							($interfaceType == INTERFACE_TYPE_ANY ? '' : ' AND type='.$interfaceType)
					));
					if ($dbInterfaces != null) {
						foreach ($dbInterfaces as $host_interface) {
							$this->zbxTestAssertElementPresentXpath('//z-select[@id="interface-select"]//li[text()="'.
									$host_interface['ip'].':'.$host_interface['port'].'"]');
						}
					}
					else {
						$this->zbxTestTextPresent('No interface found');
						$this->zbxTestAssertNotVisibleId('interface-select');
					}
					break;
				default:
					$this->zbxTestTextNotVisible(['Host interface', 'No interface found']);
					$this->zbxTestAssertNotVisibleId('interface-select');
					break;
			}
		}

		if ($type == 'IPMI agent') {
			$this->zbxTestTextPresent('IPMI sensor');
			$this->zbxTestAssertVisibleId('ipmi_sensor');
			$this->zbxTestAssertAttribute("//input[@id='ipmi_sensor']", 'maxlength', 128);
			$this->zbxTestAssertAttribute("//input[@id='ipmi_sensor']", 'size', 20);
		}
		else {
			$this->zbxTestTextNotVisible('IPMI sensor');
			$this->zbxTestAssertNotVisibleId('ipmi_sensor');
		}

		if ($type == 'SSH agent') {
			$this->zbxTestTextPresent('Authentication method');
			$this->zbxTestAssertVisibleId('authtype');
			$this->zbxTestDropdownHasOptions('authtype', ['Password', 'Public key']);
		}
		else {
			$this->zbxTestTextNotVisible('Authentication method');
			$this->zbxTestAssertNotVisibleId('authtype');
		}

		if ($type == 'SSH agent' || $type == 'TELNET agent' || $type == 'JMX agent' || $type == 'Simple check' || $type == 'Database monitor') {
			$this->zbxTestTextPresent('User name');
			$this->zbxTestAssertVisibleId('username');
			$this->zbxTestAssertAttribute("//input[@id='username']", 'maxlength', 64);
			$this->zbxTestAssertAttribute("//input[@id='username']", 'size', 20);

			if (isset($authtype) && $authtype == 'Public key') {
				$this->zbxTestTextPresent('Key passphrase');
			}
			else {
				$this->zbxTestTextPresent('Password');
			}
			$this->zbxTestAssertVisibleId('password');
			$this->zbxTestAssertAttribute("//input[@id='password']", 'maxlength', 64);
			$this->zbxTestAssertAttribute("//input[@id='password']", 'size', 20);
		}
		else {
			$this->zbxTestTextNotVisible(['User name', 'Password', 'Key passphrase']);
			$this->zbxTestAssertNotVisibleId('username');
			$this->zbxTestAssertNotVisibleId('password');
		}

		if	(isset($authtype) && $authtype == 'Public key') {
			$this->zbxTestTextPresent('Public key file');
			$this->zbxTestAssertVisibleId('publickey');
			$this->zbxTestAssertAttribute("//input[@id='publickey']", 'maxlength', 64);
			$this->zbxTestAssertAttribute("//input[@id='publickey']", 'size', 20);

			$this->zbxTestTextPresent('Private key file');
			$this->zbxTestAssertVisibleId('privatekey');
			$this->zbxTestAssertAttribute("//input[@id='privatekey']", 'maxlength', 64);
			$this->zbxTestAssertAttribute("//input[@id='privatekey']", 'size', 20);
		}
		else {
			$this->zbxTestTextNotVisible('Public key file');
			$this->zbxTestAssertNotVisibleId('publickey');

			$this->zbxTestTextNotVisible('Private key file');
			$this->zbxTestAssertNotVisibleId('publickey');
		}

		if	($type === 'SNMP agent') {
			$this->zbxTestTextPresent('SNMP OID');
			$this->zbxTestAssertVisibleId('snmp_oid');
			$this->zbxTestAssertAttribute("//input[@id='snmp_oid']", 'maxlength', 512);
			$this->zbxTestAssertAttribute("//input[@id='snmp_oid']", 'size', 20);
			if (!isset($itemid)) {
				$this->zbxTestAssertAttribute("//input[@id='snmp_oid']", 'placeholder', '[IF-MIB::]ifInOctets.1');
			}
		}
		else {
			$this->zbxTestTextNotVisible('SNMP OID');
			$this->zbxTestAssertNotVisibleId('snmp_oid');
		}

		switch ($type) {
			case 'Zabbix agent':
			case 'Zabbix agent (active)':
			case 'Simple check':
			case 'SNMP agent':
			case 'Zabbix internal':
			case 'External check':
			case 'Database monitor':
			case 'IPMI agent':
			case 'SSH agent':
			case 'TELNET agent':
			case 'JMX agent':
			case 'Calculated':
				$this->zbxTestTextPresent('Update interval');
				$this->zbxTestAssertVisibleId('delay');
				$this->zbxTestAssertAttribute("//input[@id='delay']", 'maxlength', 255);
				$this->zbxTestAssertAttribute("//input[@id='delay']", 'size', 20);
				if (!isset($itemid)) {
					$this->zbxTestAssertElementValue('delay', '1m');
				}
				break;
			default:
				$this->zbxTestTextNotVisible('Update interval');
				$this->zbxTestAssertNotVisibleId('delay');
		}

		$this->zbxTestTextPresent('Type of information');
		if (!isset($templateid)) {
			$this->zbxTestAssertVisibleId('value_type');
			$this->zbxTestDropdownHasOptions('value_type', [
				'Numeric (unsigned)',
				'Numeric (float)',
				'Character',
				'Log',
				'Text'
			]);

			$this->zbxTestIsEnabled("//*[@id='value_type']//li[text()='Numeric (unsigned)']");
			$this->zbxTestIsEnabled("//*[@id='value_type']//li[text()='Numeric (float)']");

			if ($type == 'Calculated') {
				$this->zbxTestAssertAttribute("//*[@id='value_type']//li[text()='Character']", 'disabled');
				$this->zbxTestAssertAttribute("//*[@id='value_type']//li[text()='Log']", 'disabled');
				$this->zbxTestAssertAttribute("//*[@id='value_type']//li[text()='Text']", 'disabled');
			}
			else {
				$this->zbxTestIsEnabled("//*[@id='value_type']//li[text()='Character']");
				$this->zbxTestIsEnabled("//*[@id='value_type']//li[text()='Log']");
				$this->zbxTestIsEnabled("//*[@id='value_type']//li[text()='Text']");
			}
		}
		else {
			$this->zbxTestAssertVisibleId('value_type');
			$this->zbxTestAssertAttribute("//z-select[@id='value_type']", 'readonly');
		}

		if ($value_type === 'Numeric (float)' || ($value_type == 'Numeric (unsigned)')) {
			$this->zbxTestTextPresent('Units');
			$this->zbxTestAssertVisibleId('units');
			$this->zbxTestAssertAttribute("//input[@id='units']", 'maxlength', 255);
			$this->zbxTestAssertAttribute("//input[@id='units']", 'size', 20);
			if(isset($templateid)) {
				$this->zbxTestAssertAttribute("//input[@id='units']", 'readonly');
			}
		}
		else {
			$this->zbxTestTextNotVisible('Units');
			$this->zbxTestAssertNotVisibleId('units');
		}

		// Custom intervals isn't visible for type 'SNMP trap' and 'Zabbix trapper'
		if ($type === 'SNMP trap' || $type === 'Zabbix trapper') {
			$this->zbxTestTextNotVisible(['Custom intervals', 'Interval', 'Period']);
			$this->zbxTestAssertNotVisibleId('delayFlexTable');

			$this->zbxTestTextNotVisible(['Flexible', 'Scheduling']);
			$this->zbxTestAssertNotVisibleId('delay_flex_0_delay');
			$this->zbxTestAssertNotVisibleId('delay_flex_0_period');
			$this->zbxTestAssertNotVisibleId('interval_add');
		}
		else {
			$this->zbxTestTextPresent(['Custom intervals', 'Interval',  'Period', 'Action']);
			$this->zbxTestAssertVisibleId('delayFlexTable');

			$this->zbxTestTextPresent(['Flexible', 'Scheduling', 'Update interval']);
			$this->zbxTestAssertVisibleId('delay_flex_0_delay');
			$this->zbxTestAssertAttribute("//input[@id='delay_flex_0_delay']", 'maxlength', 255);
			$this->zbxTestAssertAttribute("//input[@id='delay_flex_0_delay']", 'size', 20);
			$this->zbxTestAssertAttribute("//input[@id='delay_flex_0_delay']", 'placeholder', '50s');

			$this->zbxTestAssertVisibleId('delay_flex_0_period');
			$this->zbxTestAssertAttribute("//input[@id='delay_flex_0_period']", 'maxlength', 255);
			$this->zbxTestAssertAttribute("//input[@id='delay_flex_0_period']", 'size', 20);
			$this->zbxTestAssertAttribute("//input[@id='delay_flex_0_period']", 'placeholder', '1-7,00:00-24:00');
			$this->zbxTestAssertVisibleId('interval_add');
		}

		$this->zbxTestTextPresent('History storage period');
		$this->zbxTestAssertVisibleId('history');
		$this->zbxTestAssertAttribute("//input[@id='history']", 'maxlength', 255);
		if (!isset($itemid)) {
			$this->zbxTestAssertElementValue('history', '90d');
		}
		$this->zbxTestAssertAttribute("//input[@id='history']", 'size', 20);

		if ($value_type == 'Numeric (unsigned)' || $value_type == 'Numeric (float)') {
			$this->zbxTestTextPresent('Trend storage period');
			$this->zbxTestAssertVisibleId('trends');
			$this->zbxTestAssertAttribute("//input[@id='trends']", 'maxlength', 255);
			if (!isset($itemid)) {
				$this->zbxTestAssertElementValue('trends', '365d');
			}
			$this->zbxTestAssertAttribute("//input[@id='trends']", 'size', 20);
		}
		else {
			$this->zbxTestTextNotVisible('Trend storage period');
			$this->zbxTestAssertNotVisibleId('trends');
		}

		if ($value_type == 'Numeric (float)' || $value_type == 'Numeric (unsigned)' || $value_type == 'Character') {
			$this->zbxTestTextPresent('Value mapping');
			$valuemap_field = $this->query('name:itemForm')->asForm()->one()->getField('Value mapping');
			if (!isset($templateid)) {
				$this->assertEquals([], $valuemap_field->getValue());

				$db_valuemap = [];
				$valuemap_result = DBselect('SELECT name FROM valuemap WHERE hostid='.$host_info['hostid']);
				while ($row = DBfetch($valuemap_result)) {
					$db_valuemap[] = $row['name'];
				}
				$db_mappings = CDBHelper::getAll('SELECT vm.name, m.sortorder, m.value, m.newvalue FROM valuemap vm INNER JOIN'.
						' valuemap_mapping m ON m.valuemapid = vm.valuemapid WHERE vm.hostid='.$host_info['hostid'].
						' ORDER BY vm.name, m.sortorder');

				$valuemap_field->edit();
				$valuemap_overlay = COverlayDialogElement::find()->one()->waitUntilReady();
				if ($db_valuemap !== []) {
					$this->assertEquals('Value mapping', $valuemap_overlay->getTitle());
					$valuemap_table = $valuemap_overlay->query('class:list-table')->one()->asTable();
					$this->assertEquals(['Name', 'Mapping'], $valuemap_table->getHeadersText());

					$expected_count = (count($db_valuemap) > 3) ? 3 : count($db_valuemap);
					$table_rows = $valuemap_table->getRows();
					$this->assertEquals($expected_count, $table_rows->count());
					foreach($table_rows as $value_mapping) {
						$valuemap_name = ltrim($value_mapping->getColumn('Name')->getText(), $host_name.': ');
						$this->assertTrue(in_array($valuemap_name, $db_valuemap));

						$mappings = [];
						$i = 0;
						foreach ($db_mappings as $db_mapping) {
							if ($db_mapping['name'] === $valuemap_name) {
								if ($i < 3) {
									$mappings[] = '='.$db_mapping['value'].' ⇒ '.$db_mapping['newvalue'];
									$i++;
								}
								else {
									$mappings[] = '…';

									break;
								}
							}
						}
						// Transform newlines in value map table text.
						$source = $value_mapping->getColumn('Mapping')->getText();
						$text = rtrim(preg_replace("/(.*)\n⇒\n(.*)\n?/", "\\1 ⇒ \\2\n", $source), "\n");
						$this->assertEquals(implode("\n", $mappings), $text);
					}
				}
				else {
					$this->assertEquals('No data found.', $valuemap_overlay->query('class:nothing-to-show')->one()->getText());
				}
				$valuemap_overlay->close();
			}
			else {
				$this->assertTrue($valuemap_field->isValid());
				$this->assertFalse($valuemap_field->isEnabled());
			}
		}
		else {
			$this->assertFalse($this->query('xpath://label[text()="Value mapping"]/../..')->one()->isDisplayed());
		}

		if ($type == 'Zabbix trapper') {
			$this->zbxTestTextPresent('Allowed hosts');
			$this->zbxTestAssertVisibleId('trapper_hosts');
			$this->zbxTestAssertAttribute("//input[@id='trapper_hosts']", 'maxlength', 255);
			$this->zbxTestAssertAttribute("//input[@id='trapper_hosts']", 'size', 20);
		}
		else {
			$this->zbxTestTextNotVisible('Allowed hosts');
			$this->zbxTestAssertNotVisibleId('trapper_hosts');
		}

		if ($value_type == 'Log') {
			$this->zbxTestTextPresent('Log time format');
			$this->zbxTestAssertVisibleId('logtimefmt');
			$this->zbxTestAssertAttribute("//input[@id='logtimefmt']", 'maxlength', 64);
			$this->zbxTestAssertAttribute("//input[@id='logtimefmt']", 'size', 20);
		}
		else {
			$this->zbxTestTextNotVisible('Log time format');
			$this->zbxTestAssertNotVisibleId('logtimefmt');
		}

		$this->zbxTestTextNotPresent(['Applications', 'New application']);

		if ($value_type != 'Log') {
			$this->zbxTestTextPresent('Populates host inventory field');
			$this->zbxTestDropdownHasOptions('inventory_link', [
				'-None-',
				'Type',
				'Type (Full details)',
				'Name',
				'Alias',
				'OS',
				'OS (Full details)',
				'OS (Short)',
				'Serial number A',
				'Serial number B',
				'Tag',
				'Asset tag',
				'MAC address A',
				'MAC address B',
				'Hardware',
				'Hardware (Full details)',
				'Software',
				'Software (Full details)',
				'Software application A',
				'Software application B',
				'Software application C',
				'Software application D',
				'Software application E',
				'Contact',
				'Location',
				'Location latitude',
				'Location longitude',
				'Notes',
				'Chassis',
				'Model',
				'HW architecture',
				'Vendor',
				'Contract number',
				'Installer name',
				'Deployment status',
				'URL A',
				'URL B',
				'URL C',
				'Host networks',
				'Host subnet mask',
				'Host router',
				'OOB IP address',
				'OOB subnet mask',
				'OOB router',
				'Date HW purchased',
				'Date HW installed',
				'Date HW maintenance expires',
				'Date HW decommissioned',
				'Site address A',
				'Site address B',
				'Site address C',
				'Site city',
				'Site state / province',
				'Site country',
				'Site ZIP / postal',
				'Site rack location',
				'Site notes',
				'Primary POC name',
				'Primary POC email',
				'Primary POC phone A',
				'Primary POC phone B',
				'Primary POC cell',
				'Primary POC screen name',
				'Primary POC notes',
				'Secondary POC name',
				'Secondary POC email',
				'Secondary POC phone A',
				'Secondary POC phone B',
				'Secondary POC cell',
				'Secondary POC screen name',
				'Secondary POC notes'
			]);
			$this->zbxTestDropdownAssertSelected('inventory_link', '-None-');
		}

		$this->zbxTestTextPresent('Description');
		$this->zbxTestAssertVisibleId('description');
		$this->zbxTestAssertAttribute("//textarea[@id='description']", 'rows', 7);

		$this->zbxTestTextPresent('Enabled');
		$this->zbxTestAssertElementPresentId('status');
		$this->assertTrue($this->zbxTestCheckboxSelected('status'));

		$this->zbxTestAssertVisibleId('cancel');
		$this->zbxTestAssertElementText("//button[@id='cancel']", 'Cancel');

		if (isset($itemid)) {
			$this->zbxTestAssertVisibleId('clone');
			$this->zbxTestAssertElementValue('clone', 'Clone');
		}
		else {
			$this->zbxTestAssertElementNotPresentId('clone');
		}

		if (isset($itemid) && $status != HOST_STATUS_TEMPLATE) {
			$this->zbxTestAssertVisibleId('del_history');
			$this->zbxTestAssertElementValue('del_history', 'Clear history and trends');
		}
		else {
			$this->zbxTestAssertElementNotPresentId('del_history');
		}

		if ((isset($itemid) && !isset($templateid))) {
			$this->zbxTestAssertVisibleId('delete');
			$this->zbxTestAssertElementValue('delete', 'Delete');
			$this->zbxTestAssertVisibleId('update');
			$this->zbxTestAssertElementValue('update', 'Update');
		}
		elseif (isset($templateid)) {
			$this->zbxTestAssertElementPresentXpath("//button[@id='delete'][@disabled]");
		}
		else {
			$this->zbxTestAssertElementNotPresentId('delete');
		}

		if (isset($templateid) && array_key_exists('preprocessing', $data)) {
			$this->zbxTestTabSwitch('Preprocessing');
			$dbResult = DBselect('SELECT * FROM item_preproc WHERE itemid='.$itemid);
			$itemsPreproc = DBfetchArray($dbResult);
			foreach ($itemsPreproc as $itemPreproc) {
				// The array of allowed types must be synced with CItem::SUPPORTED_PREPROCESSING_TYPES.
				$preprocessing_type = get_preprocessing_types($itemPreproc['type'], false,
					CItem::SUPPORTED_PREPROCESSING_TYPES
				);
				$this->zbxTestAssertAttribute("//z-select[@id='preprocessing_".($itemPreproc['step']-1)."_type']", 'readonly');
				$this->zbxTestDropdownAssertSelected("preprocessing_".($itemPreproc['step']-1)."_type", $preprocessing_type);
				if ((1 <= $itemPreproc['type']) && ($itemPreproc['type'] <= 4)) {
					$this->zbxTestAssertAttribute("//input[@id='preprocessing_".($itemPreproc['step']-1)."_params_0']", 'readonly');
					$this->zbxTestAssertElementValue("preprocessing_".($itemPreproc['step']-1)."_params_0", $itemPreproc['params']);
				}
				elseif ($itemPreproc['type'] == 5) {
					$reg_exp = preg_split("/\n/", $itemPreproc['params']);
					$this->zbxTestAssertAttribute("//input[@id='preprocessing_".($itemPreproc['step']-1)."_params_0']", 'readonly');
					$this->zbxTestAssertAttribute("//input[@id='preprocessing_".($itemPreproc['step']-1)."_params_1']", 'readonly');
					$this->zbxTestAssertElementValue("preprocessing_".($itemPreproc['step']-1)."_params_0", $reg_exp[0]);
					$this->zbxTestAssertElementValue("preprocessing_".($itemPreproc['step']-1)."_params_1", $reg_exp[1]);
				}
			}
		}
	}

	// Returns update data
	public static function update() {
		return CDBHelper::getDataProvider("SELECT * FROM items WHERE hostid = 40001 AND key_ LIKE 'test-item-form%'");
	}

	/**
	 * @dataProvider update
	 */
	public function testFormItem_SimpleUpdate($data) {
		$name = $data['name'];

		$sqlItems = "SELECT * FROM items ORDER BY itemid";
		$oldHashItems = CDBHelper::getHash($sqlItems);

		$this->zbxTestLogin('hosts.php');
		$this->zbxTestClickLinkTextWait($this->host);
		$this->zbxTestClickXpathWait('//div[@class="header-navigation"]//a[text()="Items"]');
		$this->zbxTestClickLinkTextWait($name);
		$this->zbxTestClickWait('update');
		$this->zbxTestCheckTitle('Configuration of items');
		$this->zbxTestWaitUntilMessageTextPresent('msg-good', 'Item updated');
		$this->zbxTestTextPresent($name);
		$this->zbxTestCheckHeader('Items');

		$this->assertEquals($oldHashItems, CDBHelper::getHash($sqlItems));
	}

	// Returns create data
	public static function create() {
		return [
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Checksum of $1',
					'key' => 'vfs.file.cksum[/sbin/shutdown]',
					'dbName' => 'Checksum of /sbin/shutdown',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Duplicate item
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Checksum of $1',
					'key' => 'vfs.file.cksum[/sbin/shutdown]',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item with key "vfs.file.cksum[/sbin/shutdown]" already exists on'
					]
				]
			],
			// Item name is missing
			[
				[
					'expected' => TEST_BAD,
					'key' =>'item-name-missing',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Incorrect value for field "Name": cannot be empty.'
					]
				]
			],
			// Item key is missing
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item name',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Incorrect value for field "Key": cannot be empty.'
					]
				]
			],
			// Empty timedelay
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item delay',
					'key' => 'item-delay-test',
					'delay' => 0,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Specified update interval requires having at least one either flexible or scheduling interval.'
					]
				]
			],
			// Incorrect timedelay
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item delay',
					'key' => 'item-delay-test',
					'delay' => '-30',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Field "Update interval" is not correct: a time unit is expected'
					]
				]
			],
			// Incorrect timedelay
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item delay',
					'key' => 'item-delay-test',
					'delay' => 86401,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Update interval should be between 1s and 1d. Also Scheduled/Flexible intervals can be used.'
					]
				]
			],
			// Empty time flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-11,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1-11,00:00-24:00".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-25:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1-7,00:00-25:00".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,24:00-00:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1-7,24:00-00:00".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00;2,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1,00:00-24:00;2,00:00-24:00".'
					]
				]
			],
			// Multiple flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay1',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'delay' => 0,
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex combined with flex periods',
					'key' => 'item-flex-delay2',
					'delay' => 0,
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					],
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay3',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay4',
					'delay' => 0,
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay5',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Item will not be refreshed. Please enter a correct update interval.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay6',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '2,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '3,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '4,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '5,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '6,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '7,00:00-24:00', 'remove' => true],
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay7',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00', 'remove' => true],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex Check',
					'key' => 'item-flex-delay8',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00', 'remove' => true],
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					],
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Seven flexfields - save OK
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex-maximum save OK',
					'key' => 'item-flex-maximum-save',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					],
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-empty',
					'history' => ' ',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "history": a time unit is expected.'
					]
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-test',
					'history' => 3599,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "history": value must be one of 0, 3600-788400000.'
					]
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-test',
					'history' => 788400001,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "history": value must be one of 0, 3600-788400000.'
					]
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-test',
					'history' => '-1',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "history": a time unit is expected.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-empty',
					'trends' => ' ',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "trends": a time unit is expected.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-test',
					'trends' => '-1',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "trends": a time unit is expected.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-test',
					'trends' => 788400001,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "trends": value must be one of 0, 86400-788400000.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-test',
					'trends' => 86399,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "trends": value must be one of 0, 86400-788400000.'
					]
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'name' => '!@#$%^&*()_+-=[]{};:"|,./<>?',
					'key' => 'item-symbols-test',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// List of all item types
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix agent',
					'name' => 'Zabbix agent',
					'key' => 'item-zabbix-agent',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Update and custom intervals are hidden if item key is mqtt.get
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix agent (active)',
					'name' => 'Zabbix agent (active) mqtt',
					'key' => 'mqtt.get[0]',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix agent (active)',
					'name' => 'Zabbix agent (active)',
					'key' => 'item-zabbix-agent-active',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Simple check',
					'name' => 'Simple check',
					'key' => 'item-simple-check',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'SNMP agent',
					'name' => 'SNMP agent',
					'key' => 'item-snmp-agent',
					'snmp_oid' => '[IF-MIB::]ifInOctets.1',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'SNMP trap',
					'name' => 'SNMP trap',
					'key' => 'snmptrap.fallback',
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix internal',
					'name' => 'Zabbix internal',
					'key' => 'item-zabbix-internal',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix trapper',
					'name' => 'Zabbix trapper',
					'key' => 'item-zabbix-trapper',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix trapper',
					'name' => 'Zabbix trapper with macro in allowed hosts field',
					'key' => 'item-zabbix-trapper-macro',
					'allowed_hosts' => '{$TEST}',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix trapper',
					'name' => 'Zabbix trapper with macro and ip in allowed hosts field',
					'key' => 'item-zabbix-trapper-macro-ip',
					'allowed_hosts' => '{$MACRO},127.0.0.1',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'External check',
					'name' => 'External check',
					'key' => 'item-external-check',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Database monitor',
					'name' => 'Database monitor',
					'key' => 'item-database-monitor',
					'params_ap' => 'query',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent',
					'key' => 'item-ipmi-agent',
					'ipmi_sensor' => 'ipmi_sensor',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// IPMI sensor is optional if item key is ipmi.get
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent with ipmi.get',
					'key' => 'ipmi.get',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'SSH agent',
					'name' => 'SSH agent',
					'key' => 'item-ssh-agent',
					'username' => 'zabbix',
					'params_es' => 'executed script',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'TELNET agent',
					'name' => 'TELNET agent',
					'key' => 'item-telnet-agent',
					'username' => 'zabbix',
					'params_es' => 'executed script',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent error',
					'key' => 'item-ipmi-agent-error',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "ipmi_sensor": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent with spaces',
					'key' => 'item-ipmi-agent-spaces',
					'ipmi_sensor' => '  ipmi_sensor   ',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'SSH agent',
					'name' => 'SSH agent error',
					'key' => 'item-ssh-agent-error',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Incorrect value for field "User name": cannot be empty.',
						'Incorrect value for field "Executed script": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'TELNET agent',
					'name' => 'TELNET agent error',
					'key' => 'item-telnet-agent-error',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Incorrect value for field "User name": cannot be empty.',
						'Incorrect value for field "Executed script": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'JMX agent',
					'name' => 'JMX agent',
					'key' => 'item-jmx-agent',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Calculated',
					'name' => 'Calculated',
					'key' => 'item-calculated',
					'params_f' => '"formula"',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Dependent item',
					'name' => 'Dependent item',
					'key' => 'item-dependent',
					'master_item' => 'testFormItem',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Calculated',
					'name' => 'Calculated',
					'key' => 'item-calculated',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Incorrect value for field "Formula": cannot be empty.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Database monitor',
					'name' => 'Database monitor',
					'params_ap' => 'query',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Check the key, please. Default example was passed.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'SSH agent',
					'name' => 'SSH agent',
					'username' => 'zabbix',
					'params_es' => 'script to be executed',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Check the key, please. Default example was passed.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'TELNET agent',
					'name' => 'TELNET agent',
					'username' => 'zabbix',
					'params_es' => 'script to be executed',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Check the key, please. Default example was passed.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'JMX agent',
					'name' => 'JMX agent',
					'username' => 'zabbix',
					'error_msg' => 'Page received incorrect data',
					'errors' => [
						'Incorrect value for field "Key": cannot be empty.'
					]
				]
			]
		];
	}

	/**
	 * @dataProvider create
	 */
	public function testFormItem_SimpleCreate($data) {
		$this->zbxTestLogin('hosts.php');
		$this->zbxTestClickLinkTextWait($this->host);
		$this->zbxTestClickXpathWait('//div[@class="header-navigation"]//a[text()="Items"]');

		$this->zbxTestCheckTitle('Configuration of items');
		$this->zbxTestCheckHeader('Items');

		$this->zbxTestContentControlButtonClickTextWait('Create item');
		$this->zbxTestCheckTitle('Configuration of items');

		if (isset($data['type'])) {
			$this->zbxTestDropdownSelect('type', $data['type']);
			$type = $data['type'];
		}
		else {
			$type = $this->zbxTestGetSelectedLabel('type');
		}

		if (isset($data['name'])) {
			$this->zbxTestInputType('name', $data['name']);
		}
		$name = $this->zbxTestGetValue("//input[@id='name']");

		if (isset($data['key'])) {
			$this->zbxTestInputType('key', $data['key']);
		}
		$key = $this->zbxTestGetValue("//input[@id='key']");

		if (isset($data['username'])) {
			$this->zbxTestInputType('username', $data['username']);
		}

		if (isset($data['ipmi_sensor'])) {
			$this->zbxTestInputType('ipmi_sensor', $data['ipmi_sensor']);
			$ipmi_sensor = $this->zbxTestGetValue("//input[@id='ipmi_sensor']");
		}

		if (isset($data['allowed_hosts'])) {
			$this->zbxTestInputType('trapper_hosts', $data['allowed_hosts']);
		}

		if (isset($data['params_f'])) {
			$this->zbxTestInputType('params_f', $data['params_f']);
		}

		if (isset($data['params_es'])) {
			$this->zbxTestInputTypeWait('params_es', $data['params_es']);
		}

		if (isset($data['params_ap'])) {
			$this->zbxTestInputTypeWait('params_ap', $data['params_ap']);
		}

		if (isset($data['delay']))	{
			$this->zbxTestInputTypeOverwrite('delay', $data['delay']);
		}

		if (array_key_exists('master_item',$data))	{
			$this->zbxTestClickButtonMultiselect('master_itemid');
			$this->zbxTestLaunchOverlayDialog('Items');
			$this->zbxTestClickLinkTextWait($data['master_item']);
		}

		if (array_key_exists('snmp_oid', $data))	{
			$this->zbxTestInputTypeOverwrite('snmp_oid', $data['snmp_oid']);
		}

		// Check hidden update and custom interval for mqtt.get key.
		if (CTestArrayHelper::get($data, 'type') === 'Zabbix agent (active)'
				&& substr(CTestArrayHelper::get($data, 'key'), 0, 8) === 'mqtt.get') {
			$this->zbxTestTextNotVisible('Update interval');
			$this->zbxTestAssertNotVisibleId('row_delay');
			$this->zbxTestTextNotVisible('Custom intervals');
			$this->zbxTestAssertNotVisibleId('row_flex_intervals');
		}

		$itemFlexFlag = true;
		if (isset($data['flexPeriod'])) {

			$itemCount = 0;
			foreach ($data['flexPeriod'] as $period) {
				$this->zbxTestInputType('delay_flex_'.$itemCount.'_period', $period['flexTime']);

				if (isset($period['flexDelay'])) {
					$this->zbxTestInputType('delay_flex_'.$itemCount.'_delay', $period['flexDelay']);
				}
				$itemCount ++;
				$this->zbxTestClickWait('interval_add');

				$this->zbxTestAssertVisibleId('delay_flex_'.$itemCount.'_delay');
				$this->zbxTestAssertVisibleId('delay_flex_'.$itemCount.'_period');

				if (isset($period['remove'])) {
					$this->zbxTestClick('delay_flex_'.($itemCount-1).'_remove');
				}
			}
		}

		if (isset($data['history'])) {
			$this->zbxTestInputTypeOverwrite('history', $data['history']);
		}

		if (isset($data['trends'])) {
			$this->zbxTestInputTypeOverwrite('trends', $data['trends']);
		}

		switch ($type) {
			case 'Zabbix agent':
			case 'Simple check':
			case 'SNMP agent':
			case 'SNMP trap':
			case 'External check':
			case 'IPMI agent':
			case 'SSH agent':
			case 'TELNET agent':
			case 'JMX agent':
				$interfaceid = $this->zbxTestGetText('//z-select[@id="interface-select"]//li[not(@disabled)]');
				break;
			default:
				$this->zbxTestAssertNotVisibleId('interface-select');
		}

		$value_type = $this->zbxTestGetSelectedLabel('value_type');
		if ($itemFlexFlag == true) {
			$this->zbxTestClickWait('add');
			$expected = $data['expected'];
			switch ($expected) {
				case TEST_GOOD:
					$this->zbxTestCheckTitle('Configuration of items');
					$this->zbxTestWaitUntilMessageTextPresent('msg-good', 'Item added');
					break;

				case TEST_BAD:
					$this->zbxTestCheckTitle('Configuration of items');
					$this->zbxTestWaitUntilMessageTextPresent('msg-bad', $data['error_msg']);
					foreach ($data['errors'] as $msg) {
						$this->zbxTestTextPresent($msg);
					}
					$this->zbxTestTextPresent(['Host', 'Name', 'Key']);
					if (isset($data['formula'])) {
						$this->zbxTestAssertElementValue('formula', $data['formulaValue']);
					}
					break;
				}
			}

		if (isset($data['dbCheck'])) {
			$result = DBselect("SELECT name,key_,value_type FROM items where hostid=40001 and key_ = '".$key."'");
			while ($row = DBfetch($result)) {
				$this->assertEquals($row['name'], $name);
				$this->assertEquals($row['key_'], $key);

				switch($row['value_type'])	{
					case ITEM_VALUE_TYPE_FLOAT:
						$value_typeDB = 'Numeric (float)';
						break;
					case ITEM_VALUE_TYPE_STR:
						$value_typeDB = 'Character';
						break;
					case ITEM_VALUE_TYPE_LOG:
						$value_typeDB = 'Log';
						break;
					case ITEM_VALUE_TYPE_UINT64:
						$value_typeDB = 'Numeric (unsigned)';
						break;
					case ITEM_VALUE_TYPE_TEXT:
						$value_typeDB = 'Text';
						break;
				}
				$this->assertEquals($value_typeDB, $value_type);
			}
		}
		if (isset($data['formCheck'])) {
			if (isset ($data['dbName'])) {
				$dbName = $data['dbName'];
			}
			else {
				$dbName = $name;
			}
			$this->zbxTestClickXpath("//form[@name='items']//a[text()='$dbName']");
			$this->zbxTestWaitUntilElementVisible(WebDriverBy::id('name'));
			$this->zbxTestAssertElementValue('name', $name);
			$this->zbxTestAssertElementValue('key', $key);
			$this->zbxTestAssertElementPresentXpath("//z-select[@id='type']//li[text()='$type']");
			switch ($type) {
				case 'Zabbix agent':
				case 'Simple check':
				case 'SNMP agent':
				case 'SNMP trap':
				case 'External check':
				case 'IPMI agent':
				case 'SSH agent':
				case 'TELNET agent':
				case 'JMX agent':
					$this->zbxTestAssertElementPresentXpath('//z-select[@id="interface-select"]//li[text()="'.$interfaceid.'"]');
					break;
				case 'Zabbix agent (active)':
					$this->zbxTestAssertNotVisibleId('interfaceid');
					// Check hidden update and custom interval for mqtt.get key.
					if (substr(CTestArrayHelper::get($data, 'key'), 0, 8) === 'mqtt.get') {
						$this->zbxTestTextNotVisible('Update interval');
						$this->zbxTestAssertNotVisibleId('row_delay');
						$this->zbxTestTextNotVisible('Custom intervals');
						$this->zbxTestAssertNotVisibleId('row_flex_intervals');
					}
					else {
						$this->zbxTestTextVisible('Update interval');
						$this->zbxTestAssertVisibleId('row_delay');
						$this->zbxTestTextVisible('Custom intervals');
						$this->zbxTestAssertVisibleId('row_flex_intervals');
					}
					break;
				default:
					$this->zbxTestAssertNotVisibleId('interface-select');
			}
			$this->zbxTestAssertElementPresentXpath("//z-select[@id='value_type']//li[text()='$value_type']");

			// "Check now" button availability
			if (in_array($type, ['Zabbix agent', 'Simple check', 'SNMP agent', 'Zabbix internal', 'External check',
					'Database monitor', 'IPMI agent', 'SSH agent', 'TELNET agent', 'JMX agent', 'Calculated'])) {
				$this->zbxTestClick('check_now');
				$this->zbxTestWaitUntilMessageTextPresent('msg-good', 'Request sent successfully');
			}
			else {
				$this->zbxTestAssertElementPresentXpath("//button[@id='check_now'][@disabled]");
			}

			if (isset($data['ipmi_sensor'])) {
				$ipmiValue = $this->zbxTestGetValue("//input[@id='ipmi_sensor']");
				$this->assertEquals($ipmi_sensor, $ipmiValue);
			}
		}
	}

	public function testFormItem_HousekeeperUpdate() {
		$this->zbxTestLogin('zabbix.php?action=gui.edit');
		$this->query('id:page-title-general')->asPopupButton()->one()->select('Housekeeping');

		$this->zbxTestCheckboxSelect('hk_history_global', false);
		$this->zbxTestCheckboxSelect('hk_trends_global', false);

		$this->zbxTestClickWait('update');

		$this->zbxTestOpen('hosts.php');
		$this->zbxTestClickLinkTextWait($this->host);
		$this->zbxTestClickXpathWait('//div[@class="header-navigation"]//a[text()="Items"]');
		$this->zbxTestClickLinkTextWait($this->item);

		$this->zbxTestAssertElementNotPresentId('history_mode_hint');
		$this->zbxTestAssertElementNotPresentId('trends_mode_hint');

		$this->zbxTestOpen('zabbix.php?action=gui.edit');
		$this->query('id:page-title-general')->asPopupButton()->one()->select('Housekeeping');

		$this->zbxTestCheckboxSelect('hk_history_global');
		$this->zbxTestInputType('hk_history', '99d');

		$this->zbxTestCheckboxSelect('hk_trends_global');
		$this->zbxTestInputType('hk_trends', '455d');

		$this->zbxTestClickWait('update');

		$this->zbxTestOpen('hosts.php');
		$this->zbxTestClickLinkTextWait($this->host);
		$this->zbxTestClickXpathWait('//div[@class="header-navigation"]//a[text()="Items"]');
		$this->zbxTestClickLinkTextWait($this->item);

		$this->zbxTestClickWait('history_mode_hint');
		$this->zbxTestAssertElementText("//div[@class='overlay-dialogue']", 'Overridden by global housekeeping settings (99d)');
		$this->zbxTestClickWait('trends_mode_hint');
		$this->zbxTestAssertElementText("//div[@class='overlay-dialogue'][2]", 'Overridden by global housekeeping settings (455d)');

		$this->zbxTestOpen('zabbix.php?action=gui.edit');
		$this->query('id:page-title-general')->asPopupButton()->one()->select('Housekeeping');

		$this->zbxTestInputType('hk_history', 90);
		$this->zbxTestCheckboxSelect('hk_history_global', false);

		$this->zbxTestInputType('hk_trends', 365);
		$this->zbxTestCheckboxSelect('hk_trends_global', false);

		$this->zbxTestClickWait('update');

		$this->zbxTestOpen('hosts.php');
		$this->zbxTestClickLinkTextWait($this->host);
		$this->zbxTestClickXpathWait('//div[@class="header-navigation"]//a[text()="Items"]');
		$this->zbxTestClickLinkTextWait($this->item);

		$this->zbxTestAssertElementNotPresentId('history_mode_hint');
		$this->zbxTestAssertElementNotPresentId('trends_mode_hint');
	}
}
